import { TUnityType, UGUIAltas, UnityEngine } from "../typings/unity.js";
import { EGUID, PrefabParser, UnityElement } from "../unity/PrefabParser.js";
import { UnityHelper } from "./UnityHelper.js";

export interface IUsage {
    type: TUnityType | 'Image' | 'RawImage' | 'Toggle' | 'UGUIAltas'
    path: string
    image: string
}

export class PrefabSearcher {

    private UGUIAltasGUID: string | null = null;

    public async findImageUsages(prefabFile: string, guids: string[]): Promise<IUsage[]> {
        this.UGUIAltasGUID = await UnityHelper.getScriptGUID('UGUIAltas.cs');

        const usages: IUsage[] = [];
        const pp = new PrefabParser();
        const prefab = await pp.parse(prefabFile);
        for (const e of prefab) {
            // console.log('check top element:', e.type, e.fileID);
            this.findImageUsageInternal(e, guids, '', usages);
        }
        return usages;
    }

    private findImageUsageInternal(element: UnityElement, guids: string[], path: string, usages: IUsage[]): void {
        if (element.type == 'GameObject') {
            path += '.' + (element.object as UnityEngine.GameObject).m_Name;
            const image = element.components['MonoBehaviour_' + EGUID.Image] as UnityElement<UnityEngine.UI.Image>;
            if (image != null) {
                const spriteGUID = image.object.m_Sprite.guid;
                if (guids.includes(spriteGUID)) {
                    usages.push({ type: 'Image', path, image: spriteGUID });
                }
            }
            const rawImage = element.components['MonoBehaviour_' + EGUID.RawImage] as UnityElement<UnityEngine.UI.RawImage>;
            if (rawImage != null) {
                const textureGUID = rawImage.object.m_Texture.guid;
                if (guids.includes(textureGUID)) {
                    usages.push({ type: 'RawImage', path, image: textureGUID });
                }
            }
            const toggle = element.components['MonoBehaviour_' + EGUID.Toggle] as UnityElement<UnityEngine.UI.Toggle>;
            if (toggle != null) {
                const spriteState = toggle.object.m_SpriteState;
                if (guids.includes(spriteState.m_HighlightedSprite.guid)) {
                    usages.push({ type: 'Toggle', path, image: spriteState.m_HighlightedSprite.guid });
                }
                if (guids.includes(spriteState.m_PressedSprite.guid)) {
                    usages.push({ type: 'Toggle', path, image: spriteState.m_PressedSprite.guid });
                }
                if (guids.includes(spriteState.m_SelectedSprite.guid)) {
                    usages.push({ type: 'Toggle', path, image: spriteState.m_SelectedSprite.guid });
                }
            }
            if (this.UGUIAltasGUID) {
                const uguiAltas = element.components['MonoBehaviour_' + this.UGUIAltasGUID] as UnityElement<UGUIAltas>;
                if (uguiAltas) {
                    for (const sp of uguiAltas.object.sprites) {
                        if (guids.includes(sp.guid)) {
                            usages.push({ type: 'UGUIAltas', path, image: sp.guid });
                            break;
                        }
                    }
                }
            }
            const spriteRenderer = element.components['SpriteRenderer'];
            if (spriteRenderer != null) {
                const spriteGUID = spriteRenderer.object.m_Sprite.guid;
                if (guids.includes(spriteGUID)) {
                    usages.push({ type: 'SpriteRenderer', path, image: spriteGUID });
                }
            }
            const spriteMask = element.components['SpriteMask'];
            if (spriteMask != null) {
                const spriteGUID = spriteMask.object.m_Sprite.guid;
                if (guids.includes(spriteGUID)) {
                    usages.push({ type: 'SpriteMask', path, image: spriteGUID });
                }
            }
            if (element.children != null) {
                for (const c of element.children) {
                    this.findImageUsageInternal(c, guids, path, usages);
                }
            }
        }
    }

    public async findScriptUsages(prefabFile: string, guids: string[]): Promise<IUsage[]> {
        const usages: IUsage[] = [];
        const pp = new PrefabParser();
        const prefab = await pp.parse(prefabFile);
        for (const e of prefab) {
            // console.log('check top element:', e.type, e.fileID);
            this.findScriptUsageInternal(e, guids, '', usages);
        }
        return usages;
    }

    private findScriptUsageInternal(element: UnityElement, guids: string[], path: string, usages: IUsage[]): void {
        if (element.type == 'GameObject') {
            path += '.' + (element.object as UnityEngine.GameObject).m_Name;
            for (const guid of guids) {
                const mono = element.components['MonoBehaviour_' + guid];
                if (mono != null) {
                    usages.push({ type: 'MonoBehaviour', path, image: guid });
                }
            }
            if (element.children != null) {
                for (const c of element.children) {
                    this.findScriptUsageInternal(c, guids, path, usages);
                }
            }
        }
    }
}
